package com.sdk.auth.filter;

import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
 * @author wst
 * @date 2023/7/5
 * 自定义请求处理器，对 @RequestBody、@RequestParam 参数进行处理
 */
public class CachedBodyRequestWrapper extends HttpServletRequestWrapper {

    /**
     * RequestBody 参数
     */
    private byte[] cachedBody;

    /**
     * RequestParam 参数
     */
    private final Map<String, String[]> cachedParam;

    public CachedBodyRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        this.cachedBody = StreamUtils.copyToByteArray(request.getInputStream());
        this.cachedParam = request.getParameterMap();
    }

    public byte[] getCachedBody() {
        return cachedBody;
    }

    public void setCachedBody(byte[] cachedBody) {
        this.cachedBody = cachedBody;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(this.cachedBody);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return bais.available() == 0;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    @Override
    public String getParameter(String name) {
        String[] values = cachedParam.get(name);
        return values != null && values.length > 0 ? values[0] : null;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return cachedParam;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> v = new Vector<>(cachedParam.keySet());
        return v.elements();
    }

    @Override
    public String[] getParameterValues(String name) {
        return cachedParam.get(name);
    }
}
